using System;
using GammaJul.ReSharper.GammaXaml.Highlightings.CSharp;
using JetBrains.Annotations;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Daemon;
using JetBrains.ReSharper.Psi;

[assembly: RegisterConfigurableSeverity(
	MismatchedDpAccessorTypeHighlighting.SeverityId,
	null,
	HighlightingGroupIds.CodeSmell,
	MismatchedDpAccessorTypeHighlighting.Description,
	MismatchedDpAccessorTypeHighlighting.Description,
	Severity.WARNING,
	false)]

namespace GammaJul.ReSharper.GammaXaml.Highlightings.CSharp {

	/// <summary>
	/// An highlighting that represent a mismatch between a dependency property field registered type
	/// and its accessor (property or attached getter/setter).
	/// </summary>
	[ConfigurableSeverityHighlighting(SeverityId, CSharpProjectFileType.Name, OverlapResolve = OverlapResolveKind.WARNING)]
	public class MismatchedDpAccessorTypeHighlighting : IHighlighting {
		internal const string SeverityId = "Dp.MismatchedDpAccessorType";
		internal const string Description = "Dependency property type doesn't match its accessor type.";

		private readonly IField _dpField;
		private readonly IType _dpRegisteredType;
		private readonly IDeclaredElement _accessor;

		/// <summary>
		/// Gets the dependency property field.
		/// </summary>
		[NotNull]
		public IField DpField {
			get { return _dpField; }
		}

		/// <summary>
		/// Gets the registered type of the dependency property.
		/// </summary>
		[NotNull]
		public IType DpRegisteredType {
			get { return _dpRegisteredType; }
		}

		/// <summary>
		/// Gets the accessor.
		/// </summary>
		[NotNull]
		public IDeclaredElement Accessor {
			get { return _accessor; }
		}

		public string ToolTip {
			get { return Description; }
		}

		public string ErrorStripeToolTip {
			get { return Description; }
		}

		public int NavigationOffsetPatch {
			get { return 0; }
		}

		public bool IsValid() {
			return _dpField.IsValid() && _accessor.IsValid();
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="MismatchedDpAccessorTypeHighlighting"/> class.
		/// </summary>
		/// <param name="dpField">The dependency property field.</param>
		/// <param name="dpRegisteredType">The registered type of the dependency property.</param>
		/// <param name="accessor">The CLR wrapper property.</param>
		public MismatchedDpAccessorTypeHighlighting([NotNull] IField dpField, [NotNull] IType dpRegisteredType, [NotNull] IDeclaredElement accessor) {
			if (dpField == null)
				throw new ArgumentNullException("dpField");
			if (dpRegisteredType == null)
				throw new ArgumentNullException("dpRegisteredType");
			if (accessor == null)
				throw new ArgumentNullException("accessor");

			_dpField = dpField;
			_dpRegisteredType = dpRegisteredType;
			_accessor = accessor;
		}
	}

}